package io.kiki.stack.http.feign.optionals;

import io.kiki.stack.http.feign.Response;
import io.kiki.stack.http.feign.Util;
import io.kiki.stack.http.feign.codec.Decoder;

import java.io.IOException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Objects;
import java.util.Optional;

public final class OptionalDecoder implements Decoder {
    final Decoder delegate;

    public OptionalDecoder(Decoder delegate) {
        Objects.requireNonNull(delegate, "Decoder must not be null. ");
        this.delegate = delegate;
    }

    static boolean isOptional(Type type) {
        if (!(type instanceof ParameterizedType parameterizedType)) {
            return false;
        }
        return parameterizedType.getRawType().equals(Optional.class);
    }

    @Override
    public Object decode(Response response, Type type) throws IOException {
        if (!isOptional(type)) {
            return delegate.decode(response, type);
        }
        if (response.status() == 404 || response.status() == 204) {
            return Optional.empty();
        }
        Type enclosedType = Util.resolveLastTypeParameter(type, Optional.class);
        return Optional.ofNullable(delegate.decode(response, enclosedType));
    }
}
